package com.sbillings.messenger.hub;

import java.util.ArrayList;
import java.util.Observer;
import java.util.Observable;

/**
 * Represents a person that wants to receive messages.
 * Implements the Observer interface to receive
 * Messages from a publisher (an Observable).
 * 
 * Manages a list of Message sources that the person is interested in receiving
 * messages from, and ignores messages not from that source.
 * 
 * Manages a list of NotificationStrategies, which are ways to notify this person (such as email, txt, etc.). When
 * an interesting messages arrives, all NotificationStrategies in that list will be invoked to
 * send the message to the person.
 * 
 * @author steve.billings
 *
 */
public class Subscriber implements Observer {
	private String name;
	private String email = null;
	private String mobile = null;
	private ArrayList<String> messageSources = new ArrayList<String>(); // Sources this person wants to listen to
	private ArrayList<NotificationStrategy> notificationStrategies = new ArrayList<NotificationStrategy>(); // The ways to notify this person

	public Subscriber(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	public String toString() {
		return "Subscriber: " + this.getName();
	}

	/**
	 * Add a NotificationStrategy to the list.
	 * @param notificationStrategy the NotificationStrategy to add to the list
	 */
	public void addNotificationStrategy(
			NotificationStrategy notificationStrategy) {
		this.notificationStrategies.add(notificationStrategy);
	}

	/**
	 * Add a message source to the list of sources this subscriber is interested in.
	 * @param messageSource
	 */
	public void addMessageSource(String messageSource) {
		this.messageSources.add(messageSource);
	}
	
	/**
	 * Remove a message source from the list of sources this subscriber is interested in.
	 * @param messageSource
	 */
	public void removeMessageSource(String messageSource) {
		this.messageSources.remove(messageSource);
	}

	/**
	 * The publisher (Observable) will call this method when a message is broadcasted.
	 * First, make sure it's a message from a MessagePublisher. If it is,
	 * make sure the source is one of the sources this subscriber is interested in.
	 * If it is, invoke all NotificationStrategies in this subscribers list to notify
	 * the person.
	 * @param publisher The publisher sending the message.
	 * @param o the message being broadcast.
	 */
	public void update(Observable publisher, Object o) {
		if (publisher instanceof MessagePublisher) {
			Message message = (Message) o;
			if (this.messageSources.contains(message.getSource())) {
				for (NotificationStrategy notificationStrategy : this.notificationStrategies) {
					notificationStrategy.sendMessage(this, (Message) message);
				}
			}

		}

	}

}
